package com.mlming.springboot.service.impl;

import com.mlming.springboot.consts.MallConst;
import com.mlming.springboot.dao.CategoryMapper;
import com.mlming.springboot.pojo.Category;
import com.mlming.springboot.service.CategoryService;
import com.mlming.springboot.vo.CategoryVo;
import com.mlming.springboot.vo.ResponseVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

@Service
public class CategoryServiceImpl implements CategoryService {
    @Autowired
    private CategoryMapper categoryMapper;

    @Override
    public ResponseVo<List<CategoryVo>> getAllCategories() {
        List<CategoryVo> categoryVoList = new ArrayList<>(); // 要返回的列表
        /*
        	由于查询数据库是非常耗时的,所以一开始直接从数据库读取所有的数据(因为类目表一般数据量不大)
        	然后再进行操作,这样就减少了对数据库的查询次数
        */
        List<Category> categories = categoryMapper.selectAll(); // 数据库中的所有类目数据
        // 1) 先获取一级目录
        for (Category category : categories) {
            // 如果parentId==0,说明是一级目录
            if(category.getParentId().equals(MallConst.ROOT_PARENT_ID)) {
                // 由于返回的是vo对象,所以必须得转成vo
                CategoryVo categoryVo = new CategoryVo();
                BeanUtils.copyProperties(category,categoryVo);
                // 将一级目录存入categoryVoList中
                categoryVoList.add(categoryVo);
                // 寻找其子目录
                findAllChildren(categoryVo,categories);
            }
        }
        // 按照业务要求,按照sortOrder字段进行排序 => 从大到小
        // 所以最后还得reserved反转一下
        categoryVoList.sort(Comparator.comparing(CategoryVo::getSortOrder).reversed());
        return ResponseVo.success(categoryVoList);
    }

    // 递归函数: 不断往下寻找多级目录
    private void findAllChildren(CategoryVo parentVo,List<Category> categories) {
        parentVo.setSubCategories(new ArrayList<>()); // 初始化子目录列表
        for (Category category : categories) {
            // 如果有一个类目的parentId == 当前parentVo的id,则说明是子目录
            if(category.getParentId().equals(parentVo.getId())) {
                // 由于返回的是vo对象,所以必须得转成vo
                CategoryVo categoryVo = new CategoryVo();
                BeanUtils.copyProperties(category,categoryVo);
                // 将子目录存到parentVo的子目录列表中
                parentVo.getSubCategories().add(categoryVo);
                // 寻找该子目录的子目录
                findAllChildren(categoryVo,categories);
            }
        }
        // 根据业务要求,要根据sortOrder字段进行排序 => 从大到小
        // 所以sort之后,还要reversed反转一下
        parentVo.getSubCategories().sort(Comparator.comparing(CategoryVo::getSortOrder).reversed());
    }

    @Override
    public void findAllCategoryIdsByCategoryId(Integer categoryId, Set<Integer> categoryIdSet) {
        List<Category> categories = categoryMapper.selectAll(); // 数据库中的所有类目数据
        findSubCategoryIds(categoryId,categoryIdSet,categories);
    }

    // 递归函数: 不断往下寻找多级目录的id
    private void findSubCategoryIds(Integer categoryId,Set<Integer> categoryIdSet,List<Category> categories) {
        for (Category category : categories) {
            if(category.getParentId().equals(categoryId)) {
                categoryIdSet.add(category.getId());
                findSubCategoryIds(category.getId(),categoryIdSet,categories);
            }
        }
    }
}
